﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rocket.Core.Common;
using Rocket.Windows.Framework.Data;
using Rocket.Core;
using Rocket.Windows.Framework.Utilities;
using System.Linq.Expressions;

namespace Rocket.Windows.Framework
{
    public abstract class BaseManager<H, V, F, E, G, DTO> : BaseManager<H, V, BaseDataEditor, G>
        where H : IHandler<V>     
        where V : BaseObject
        where F : IFormDataFilter<DTO>
        where G : IFormGridView<V>
        where E : BaseDataEditor
        where DTO : class
    {
        private IFormContainerFilter<V, DTO> _filterContainer;
        public BaseManager()
        {
        }

        public BaseManager(H h, E e, F f, G g)
            : base(h, e, g)
        {
            this.LoadWhenStart = false;
            _filterContainer = new ContainerFilter<H, V, F, DTO>(f, h);
            _filterContainer.OnDataFiltered += new DataFiltered<DTO>(_filterContainer_OnDataFiltered);
            ((Control)_filterContainer).Dock = DockStyle.Top;
            ((Control)_filterContainer).BringToFront();

            this.splitContainerMain.Panel1.Controls.Add((Control)_filterContainer);
            ((Control)_filterContainer).Height += _filterContainer.RocketHeight;
            this.GridView.LoadWhenStart = false;
            this.GridView.HideSearchOption = true;
        }

        void _filterContainer_OnDataFiltered(Expression<Func<DTO, bool>> filterExpression)
        {
            GridView.LoadData<DTO>(filterExpression);
        }

        public override void ReLoad()
        {
            Expression<Func<DTO, bool>> exp = this._filterContainer.GetFilterExpression();
            if (exp != null)
                GridView.LoadData<DTO>(exp);
            else
                base.ReLoad();
        }
    }
    
    public abstract partial class BaseManager<H, V, E, G> : BaseControl
        where H : IHandler<V>     
        where V : BaseObject
        where E : BaseDataEditor
        where G : IFormGridView<V>
    {
        private IHandler<V> _dataHandler;
        private IFormContainerEditor<V> _dataContainer;
        private IFormGridView<V> _gridView;

        public BaseManager() 
        {
        }
        public BaseManager(H h, E e, G g)
        {
            InitializeComponent();

            _dataHandler = h;
            _dataContainer = new ContainerEditor<H, V, E>(e, h);
            _gridView = g;
            _dataContainer.OnRocketTaskCompleted += new EventHandler(_dataContainer_OnRocketTaskCompleted);
            ((Control)_dataContainer).Dock = DockStyle.Fill;
            this.splitContainerMain.Panel2.Controls.Add((Control)_dataContainer);
            ((Control)_gridView).Dock = DockStyle.Fill;
            _gridView.DataRowSelected += new DataGridViewCellEventHandler(_grid_DataRowSelected);
            _gridView.EndCellEdit += new DataGridViewCellEventHandler(_gridView_EndCellEdit);
            this.splitContainerMain.Panel1.Controls.Add((Control)_gridView);
            if (this.splitContainerMain.Width > _dataContainer.RocketHeight)
                this.splitContainerMain.Panel2MinSize = _dataContainer.RocketHeight;
            else
                this.splitContainerMain.Panel2MinSize =(int) this.splitContainerMain.Width / 2;

            if (!string.IsNullOrEmpty(this._dataContainer.ManagerGroupBoxName)) this.groupBoxMain.Text = this._dataContainer.ManagerGroupBoxName;
            if (!string.IsNullOrEmpty(this._dataContainer.GridViewGroupBoxName)) this._gridView.GroupBoxName = this._dataContainer.GridViewGroupBoxName;
        }

        void _dataContainer_OnRocketTaskCompleted(object sender, EventArgs e)
        {
            this.ReLoad();
        }

        void _gridView_EndCellEdit(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                V mappedItem = (V)((DataGridViewPlus<V>)sender).CurrentRow.DataBoundItem;
                if (mappedItem != null)
                {
                    RocketResponse response = _dataHandler.Update(mappedItem);
                    if (response.StatusCode != StatusCodes.Successful)
                        this.SetMessage(string.IsNullOrEmpty(response.Message)
                            ? CoreMessages.SaveError : response.Message, MessageTypes.ErrorDisplay);
                    else
                        this.SetMessage(CoreMessages.SaveDone, MessageTypes.InfomationDisplay);
                }
            }
            catch (Exception ex)
            {
                this.SetMessage(ex.Message, MessageTypes.ErrorDisplay);
            }
        }

        void _grid_DataRowSelected(object sender, DataGridViewCellEventArgs e)
        {
            GridRowSelected(sender, e);
        }

        protected H DataHandler
        {
            get { return (H)_dataHandler; }
        }

        protected E DataContainer
        {
            get { return (E)_dataContainer; }
        }

        protected G GridView
        {
            get { return (G)_gridView; }
        }

        protected V ViewObject
        {
            get { return (V)_dataContainer.BindedView; }
        }

        public int ID
        {
            get { return this._dataContainer.IRocketEditor.ID; }
        }

        public bool LoadWhenStart
        {
            get { return GridView.LoadWhenStart; }
            set { GridView.LoadWhenStart = value; }
        }

        public Orientation ManagerOrientation
        {
            get { return this.splitContainerMain.Orientation; }
            set { this.splitContainerMain.Orientation = value; }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (LoadWhenStart)
                ReLoad();
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
        }
        /// <summary>
        /// Use this method to load data in to the main gridview
        /// </summary>
        public virtual void ReLoad()
        {
            _gridView.LoadData();
        }

        public virtual void GridRowSelected(object sender, EventArgs e)
        {
            _dataContainer.SetRocketBindingSourceView((V)sender);
            ((IFormContainerEditor<V>)_dataContainer).RocketBindingSourceChanged(sender, e);
            this._dataContainer.ID = ((IObject)sender).Id;
        }
    }
}
